SELECT

  osm_id AS __id__,

  -- boundaries return back the geometry in a different way, which is returned back in a sidecar property __boundaries_geometry__
  -- if the feature is only a boundary, we have an optimization to not calculate the intersection because the geometry is already available in the __boundaries_geometry__ property
  CASE WHEN NOT (mz_boundary_min_zoom IS NOT NULL AND
                 mz_poi_min_zoom IS NULL AND
                 mz_landuse_min_zoom IS NULL AND
                 mz_transit_level IS NULL AND
                 mz_water_min_zoom IS NULL AND
                 mz_earth_min_zoom IS NULL AND
                 mz_building_min_zoom IS NULL) THEN
    CASE WHEN mz_water_min_zoom IS NOT NULL
      -- water geometries need a padded intersection
      THEN {% filter geometry %}{{ bounds['polygon']|bbox_padded_intersection('way') }}{% endfilter %}
      ELSE {% filter geometry %}{{ bounds['polygon']|bbox_intersection('way') }}{% endfilter %}
    END
  END AS __geometry__,

  -- geometry for boundaries
  CASE WHEN mz_boundary_min_zoom IS NOT NULL
    -- note that we force the RHR, which makes outers clockwise,
    -- then take the boundary, then reverse and intersect with
    -- the query bbox. this is needed because Shapely expects a
    -- correctly-oriented outer to run counter-clockwise.
    THEN {% filter geometry %}{{ bounds['line']|bbox_intersection('st_reverse(st_boundary(st_forcerhr(way)))', 3857) }}{% endfilter %}
  END AS __boundaries_geometry__,

  -- only certain layers return the mz_label_placement property
  CASE WHEN mz_building_min_zoom IS NOT NULL OR
            mz_earth_min_zoom IS NOT NULL OR
            mz_landuse_min_zoom IS NOT NULL OR
            mz_water_min_zoom IS NOT NULL
       THEN {% filter geometry %}mz_label_placement{% endfilter %}
  END AS __label__,

  -- common properties across all layers
  to_jsonb(tags) || extra_wikidata_properties(tags->'wikidata') || jsonb_build_object(
    'source', 'openstreetmap.org',
    'area', way_area
  ) AS __properties__,

  CASE WHEN mz_boundary_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_boundary_min_zoom,
      'mz_boundary_from_polygon', TRUE
    )
  END AS __boundaries_properties__,

  CASE WHEN mz_transit_level IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_transit_level
    )
  END AS __transit_properties__,

  CASE WHEN mz_poi_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_poi_min_zoom,
      'mz_transit_score', (transit_routes).score,
      'mz_transit_root_relation_id', (transit_routes).root_relation_id,
      'train_routes', (transit_routes).train_routes,
      'subway_routes', (transit_routes).subway_routes,
      'light_rail_routes', (transit_routes).light_rail_routes,
      'tram_routes', (transit_routes).tram_routes
    )
  END AS __pois_properties__,

  CASE WHEN mz_building_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_building_min_zoom,
      'name', CASE WHEN mz_poi_min_zoom IS NULL AND mz_landuse_min_zoom IS NULL
                THEN tags->'name'
                ELSE tags->'addr:housename'
              END
    )
  END AS __buildings_properties__,

  CASE WHEN mz_water_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_water_min_zoom
    )
  END AS __water_properties__,

  CASE WHEN mz_earth_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_earth_min_zoom
    )
  END AS __earth_properties__,

  CASE WHEN mz_landuse_min_zoom IS NOT NULL
    THEN jsonb_build_object(
      'min_zoom', mz_landuse_min_zoom,
      'name', CASE WHEN mz_poi_min_zoom IS NULL THEN tags->'name' ELSE NULL END
    )
  END AS __landuse_properties__

FROM (

  SELECT
    osm_id,
    way,
    mz_label_placement,
    way_area,

    -- note: the mz_calculate_transit_routes_and_score function is pretty
    -- expensive, so we only want to calculate it when we actually need the
    -- result.
    CASE
      WHEN mz_poi_min_zoom IS NOT NULL AND
           tags ? 'railway' AND tags->'railway'='station' AND osm_id > 0
        THEN mz_calculate_transit_routes_and_score(NULL, osm_id)
      ELSE NULL
    END AS transit_routes,

    mz_building_min_zoom,
    mz_landuse_min_zoom,
    mz_poi_min_zoom,
    mz_transit_level,
    {% if zoom < 7 %}NULL AS {% endif %}mz_earth_min_zoom,
    {% if zoom < 8 %}NULL AS {% endif %}mz_water_min_zoom,
    {% if zoom < 8 %}NULL AS {% endif %}mz_boundary_min_zoom,

    tags

  FROM planet_osm_polygon

  WHERE

-- the logic for the filters is slightly different based on whether it's a boundary or not
{% if zoom >= 16 %}
    ({{ bounds['polygon']|bbox_filter('way', 3857) }} AND
     (mz_boundary_min_zoom IS NOT NULL OR
      mz_building_min_zoom IS NOT NULL OR
      mz_earth_min_zoom IS NOT NULL OR
      mz_landuse_min_zoom IS NOT NULL OR
      mz_poi_min_zoom IS NOT NULL OR
      mz_transit_level IS NOT NULL OR
      mz_water_min_zoom IS NOT NULL)) AND
    ((mz_boundary_min_zoom IS NOT NULL AND {{ bounds['line']|bbox_overlaps('way', 3857) }}) OR
     (mz_building_min_zoom IS NOT NULL OR
      mz_earth_min_zoom IS NOT NULL OR
      mz_landuse_min_zoom IS NOT NULL OR
      mz_poi_min_zoom IS NOT NULL OR
      mz_transit_level IS NOT NULL OR
      mz_water_min_zoom IS NOT NULL))
{% elif zoom >= 8 %}
    ({{ bounds['polygon']|bbox_filter('way', 3857) }} AND
     (mz_boundary_min_zoom < {{ zoom + 1 }} OR
      mz_building_min_zoom < {{ zoom + 1 }} OR
      mz_earth_min_zoom < {{ zoom + 1 }} OR
      mz_landuse_min_zoom < {{ zoom + 1 }} OR
      mz_poi_min_zoom < {{ zoom + 1 }} OR
      mz_transit_level < {{ zoom + 1 }} OR
      mz_water_min_zoom < {{ zoom + 1 }})) AND
    ((mz_boundary_min_zoom < {{ zoom + 1 }} AND {{ bounds['line']|bbox_overlaps('way', 3857) }}) OR
     (mz_building_min_zoom < {{ zoom + 1 }} OR
      mz_earth_min_zoom < {{ zoom + 1 }} OR
      mz_landuse_min_zoom < {{ zoom + 1 }} OR
      mz_poi_min_zoom < {{ zoom + 1 }} OR
      mz_transit_level < {{ zoom + 1 }} OR
      mz_water_min_zoom < {{ zoom + 1 }}))
{% elif zoom >= 7 %}
    ({{ bounds['polygon']|bbox_filter('way', 3857) }} AND
      (mz_earth_min_zoom < {{ zoom + 1 }} OR
       mz_landuse_min_zoom < {{ zoom + 1 }} OR
       mz_poi_min_zoom < {{ zoom + 1 }} OR
       mz_transit_level < {{ zoom + 1 }}))
{% else %}
    ({{ bounds['polygon']|bbox_filter('way', 3857) }} AND
      (mz_building_min_zoom < {{ zoom + 1 }} OR
       mz_landuse_min_zoom < {{ zoom + 1 }} OR
       mz_poi_min_zoom < {{ zoom + 1 }} OR
       mz_transit_level < {{ zoom + 1 }}))
{% endif %}
) p
